home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
231_01
/
drive.c
< prev
next >
Wrap
Text File
|
1987-06-15
|
14KB
|
675 lines
/*
Little Smalltalk
command parser
timothy a. budd, 12/84
*/
/*
The source code for the Little Smalltalk System may be freely
copied provided that the source of all files is acknowledged
and that this condition is copied with each file.
The Little Smalltalk System is distributed without responsibility
for the performance of the program and without any guarantee of
maintenance.
All questions concerning Little Smalltalk should be addressed to:
Professor Tim Budd
Department of Computer Science
Oregon State University
Corvallis, Oregon
97331
USA
*/
# include <stdio.h>
# include "object.h"
# define DRIVECODE
# include "drive.h"
# include "cmds.h"
# include "number.h"
# include "symbol.h"
# include "string.h"
# include "byte.h"
# include "interp.h"
# include "primitive.h"
extern enum lextokens token, nextlex();
extern int prntcmd;
extern int inisstd;
extern int started;
extern char toktext[];
extern char *lexptr;
extern int line_grabber();
extern tok_type t;
/* test_driver - see if the driver should be invoked */
int test_driver(block)
int block; /* indicates wheter to use block or non-blocking input */
{
switch(line_grabber( block )) {
default: cant_happen(17);
case -1:
/* return end of file indication */
return(0);
case 0:
/* enqueue driver process again */
return(1);
case 1:
if (*lexptr == ')') {
dolexcommand(lexptr);
return(1);
}
parse();
return(1);
}
}
/* ---- code generation routines -------------- */
# define CODEMAX 500
static uchar code[CODEMAX];
static int codetop = 0;
static gencode(value)
register int value;
{
if (value >= 256)
lexerr("code word too big: %d", value);
if (codetop > CODEMAX)
lexerr("too many code words: %d", codetop);
/*if (started)
fprintf(stderr,"code %d (%d %d)\n", value, value/16, value%16);*/
code[codetop++] = itouc(value);
}
static genhighlow(high, low)
register int high;
register int low;
{
if (high < 0 || high > 16)
lexerr("genhighlow error: %d", high);
if (low < 0)
lexerr("genhighlow low error: %d", low);
if (low < 16) gencode(high * 16 + low);
else {
gencode(TWOBIT * 16 + high);
gencode(low);
}
}
/*-------------------------------------------------------*/
static int errflag;
/* parse - main parser */
int parse()
{ register int i;
errflag = 0;
reset();
if (nextlex() == nothing) return(1);
if (token == NL) return(1);
i = aprimary();
if (i >= 0) {
asign(i);
if ((prntcmd > 1) && inisstd)
genhighlow(UNSEND, PRNTCMD);
}
else {
cexpression();
if (prntcmd && inisstd)
genhighlow(UNSEND, PRNTCMD);
}
genhighlow(POPINSTANCE, 0); /* assign to ``last'' */
if (errflag)
return(1);
if (token == nothing || token == NL) {
bld_interpreter();
return(0);
}
expect("end of expression");
return(1);
}
/* asign - code for an assignment statement - leaves result on stack */
static asign(pos)
int pos;
{ int i;
i = aprimary();
if (i >= 0) {
asign(i);
}
else {
cexpression();
}
genhighlow(SPECIAL, DUPSTACK);
genhighlow(POPINSTANCE, pos);
}
/* expression - read an expression, leaving result on stack */
static expression()
{ int i;
i = aprimary();
if (i >= 0) {
asign(i);
}
else {
cexpression();
}
}
/* cexpression - code for a (possibly cascaded) expression */
static cexpression()
{
kcontinuation();
while (token == SEMI) {
genhighlow(SPECIAL, DUPSTACK);
nextlex();
kcontinuation();
genhighlow(SPECIAL, POPSTACK);
}
}
/* kcontinuation - keyword continuation */
static kcontinuation()
{ char kbuf[150];
int kcount;
bcontinuation();
if (token == KEYWORD) {
kbuf[0] = '\0';
kcount = 0;
while (token == KEYWORD) {
strcat(kbuf, t.c);
strcat(kbuf, ":");
kcount++;
nextlex();
primary(1);
bcontinuation();
}
gensend(kbuf, kcount);
}
}
/* isbinary - see if the current token(s) is a binary */
static int isbinary(bbuf)
char *bbuf;
{
if (token == BINARY || token == MINUS ||
token == BAR || token == PE) {
strcpy(bbuf, t.c);
nextlex();
if (token == BINARY || token == MINUS ||
token == BAR || token == PE) {
strcat(bbuf, t.c);
nextlex();
}
return(1);
}
return(0);
}
/* bcontinuation - binary continuation */
static bcontinuation()
{ char bbuf[3];
ucontinuation();
while (isbinary(bbuf)) {
primary(1);
ucontinuation();
gensend(bbuf, 1);
}
}
/* ucontinuation - unary continuation */
static ucontinuation()
{
while (token == LOWERCASEVAR) {
gensend(t.c, 0);
nextlex();
}
}
/* aprimary - primary or beginning of assignment */
static int aprimary()
{ char *c;
if (token == LOWERCASEVAR) {
c = t.c;
if (nextlex() == ASSIGN) {
nextlex();
return(findvar(c, 1));
}
else {
genvar(c);
return( -1 );
}
}
primary(1);
return( - 1 );
}
/* primary - find a primary expression */
static int primary(must)
int must; /* must we find something ? */
{ int i, count;
switch(token) {
case UPPERCASEVAR:
genhighlow(PUSHCLASS, aliteral(1));
break;
case LOWERCASEVAR:
genvar(t.c);
nextlex();
break;
case LITNUM:
if (t.i >= 0 && t.i < 10) {
genhighlow(PUSHSPECIAL, t.i);
nextlex();
}
else {
genhighlow(PUSHLIT, aliteral(1));
}
break;
case MINUS:
case LITFNUM:
case LITCHAR:
case LITSTR:
case LITSYM:
case PS:
genhighlow(PUSHLIT, aliteral(1));
break;
case PSEUDO:
switch(t.p) {
case nilvar: i = 13; break;
case truevar: i = 11; break;
case falsevar: i = 12; break;
case smallvar: i = 14; break;
default: lexerr("unknown pseudo var %d", t.p);
}
genhighlow(PUSHSPECIAL, i);
nextlex();
break;
case PRIMITIVE:
if (nextlex() != LITNUM) expect("primitive number");
i = t.i;
nextlex();
count = 0;
while (primary(0)) count++;
if (token != PE) expect("primitive end");
nextlex();
genhighlow(SPECIAL, PRIMCMD);
gencode(count);
gencode(i);
break;
case LP:
nextlex();
expression();
if (token != RP) expect("right parenthesis");
nextlex();
break;
case LB:
nextlex();
block();
break;
default:
if (must) expect("primary expression");
return(0);
}
return(1);
}
static int maxtemps = 1;
static int temptop = 0;
static char *tempnames[20];
/* block - parse a block definition */
static block()
{ int count, i, position;
count = 0;
if (token == COLONVAR) {
while (token == COLONVAR) {
tempnames[temptop++] = t.c;
if (temptop > maxtemps) maxtemps = temptop;
count++;
nextlex();
}
if (token != BAR)
expect("bar following arguments in block");
nextlex();
}
genhighlow(BLOCKCREATE, count);
if (count) /* where arguments go in context */
gencode(1 + (temptop - count));
position = codetop;
gencode(0);
if (token == RB) {
genhighlow(PUSHSPECIAL, 13);
}
else
while (1) {
i = aprimary();
if (i >= 0) {
expression();
if (token != PERIOD)
genhighlow(SPECIAL, DUPSTACK);
genhighlow(POPINSTANCE, i);
}
else {
cexpression();
if (token == PERIOD)
genhighlow(SPECIAL, POPSTACK);
}
if (token != PERIOD)
break;
nextlex();
}
genhighlow(SPECIAL, RETURN);
if (token != RB) expect("end of block");
temptop -= count;
nextlex();
i = (codetop - position) - 1;
if (i > 255)
lexerr("block too big %d", i);
code[position] = itouc(i);
}
# define LITMAX 100
static object *lit_array[LITMAX];
static int littop = 0;
static int addliteral(lit)
object *lit;
{
if (littop >= LITMAX)
cant_happen(18);
sassign(lit_array[littop++], lit);
return(littop - 1);
}
/* aliteral - find a literal that is part of a literal array */
static int aliteral(must)
int must; /* must we find something ? */
{ char *c;
object *new;
int count;
int bytetop;
uchar bytes[200];
switch(token) {
case MIN